﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Bowling.Game;
using System.Text;


namespace Bowling
{
    public partial class Bowling : System.Web.UI.Page
    {
        //유저 정보와 게임 진행에 관련된 클래스를 정적 필드로 가집니다.
        private static UserInfo UserInfo = new UserInfo();
        private static GameInfo GameInfo = new GameInfo(UserInfo, DateTime.Now);
        private static GamePlay GamePlay = new GamePlay(GameInfo);
        
        /// <summary>
        /// 로그인 페이지에서 GET방식의 전달 아이디를 사용합니다.
        /// 게임 정보의 recordSeq값이 0이면 게임 스코어 기록 DB에 새로 등록합니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            
            UserInfo.userID = Request["userID"].Equals("") ? "NO ID" : Request["userID"];
            LblGamestate.Text = UserInfo.userID + "님 접속중";
            
            int seqLastRecord = new BowlingBiz_Tx().CheckLastRecordExist(UserInfo.userID);
            
            
            using (BowlingBiz_Tx bowlingBiz_Tx = new BowlingBiz_Tx())
            {
                if (seqLastRecord == -1 || GameInfo.recordSeq == -1 || GameInfo.recordSeq == 0)
                {
                    GameInfo = new GameInfo(UserInfo, DateTime.Now);
                    GamePlay = new GamePlay(GameInfo);
                    //recordSeq는 현재 진행중인 게임의 기록에 업데이트하기 위해 필요
                    GameInfo.recordSeq = bowlingBiz_Tx.AddBowlingNewGame(GameInfo);
                    bowlingBiz_Tx.SetUserInfo(UserInfo);

                    SetTruncateBowlingFrameScore();
                    pnlFrame_10.Visible = false;
                }

                SetRepeaterBowlingScore();
                
            }
            
            tbPins.Focus();
        }

        /// <summary>
        /// 새 게임 버튼 클릭의 이벤트입니다.
        /// 점수판 테이블을 클리어 해주고 게임 진행 관련 클래스들을 초기화 해 줍니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnNewGame_Click(object sender, EventArgs e)
        {
            ClearFrame();
            GameInfo = new GameInfo(UserInfo, DateTime.Now);
            GameInfo.recordSeq = 0;
            GamePlay = new GamePlay(GameInfo);
            LblGamestate.Text = UserInfo.userID + "님 새 게임 시작";
        }

        /// <summary>
        /// 롤 버튼의 클릭 이벤트입니다.
        /// 롤 텍스트박스의 값의 유효성을 검사하고 게임 플레이 롤 함수를 호출합니다.
        /// 스코어 테이블에 입력한 롤 값들을 셋팅하고 DB에 저장합니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnRoll_Click(object sender, EventArgs e)
        {
            int pins;
            
            //ERROR 값 입력 시 유효성 검사
            #region
            try
            {
                pins = Int32.Parse(tbPins.Text);
                //pins = Int32.Parse(pinsQ);

                if (pins < 0 || pins > 10)
                {
                    Response.Write("<script>alert('1~10사이의 숫자를 입력하세요')</script>");
                    return;
                }
                else if ((GamePlay.score1 + pins) > 10 || (GamePlay.score2 + pins) > 10)
                {
                    Response.Write("<script>alert('남은 핀 개수를 확인해 주세요')</script>");
                    return;
                }

            }
            catch (FormatException fe)
            {
                Response.Write("<script>alert('" + fe.Message + " : 1~10사이의 숫자를 입력하세요')</script>");
                return;
            }
            #endregion

            SetTruncateBowlingFrameScore();

            GameScore gameScore = GamePlay.Roll(pins);
            if (gameScore.isEndGame == true)
            {
                Response.Write("<script>alert('게임이 종료 되었습니다')</script>");
                gameScore.isEndGame = false;
            }

            //스코어 레이블에 입력 핀 값 셋
            SetBowlingPinScore(gameScore.p_gameInfo, gameScore.p_frameNo, gameScore.p_throwCnt, gameScore.p_score);
            SetBowlingFrameScore(gameScore.f_gameInfo, gameScore.f_frameNo, gameScore.f_score);
            
            //DB 저장
            using (BowlingBiz_Tx bowlingBiz_Tx = new BowlingBiz_Tx())
            {
                GameInfo.endDate = DateTime.Now;
                bowlingBiz_Tx.AddBowlingGameScore(GameInfo, GamePlay);

                //리피터에 데이터 바인딩 셋
                SetRepeaterBowlingScore();
                
            }


            tbPins.Text = "";
            pnlFrame_10.Visible = true;
        }

        /// <summary>
        /// 게임 저장 버튼 이벤트입니다.
        /// 현재까지 진행된 게임 점수를 업데이트합니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// 
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            SetTruncateBowlingFrameScore();

            using (BowlingBiz_Tx bowlingBiz_Tx = new BowlingBiz_Tx())
            {
                bowlingBiz_Tx.AddBowlingGameScore(GameInfo, GamePlay);
            }
        }

        /// <summary>
        /// 현재 아이디의 마지막 기록이 있는지 없는지?? 확인하는 메소드 추가
        /// 있다면 마지막 기록 셋, 없다면 pass
        /// 있다면 seqNo, 없다면 -1이 리턴 될 것이다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnLoad_Click(object sender, EventArgs e)
        {
            GameInfo.waitFrameList = new ArrayList();

            //게임을 로드할 seq번호가 입력되지 않으면 0값을 주고 마지막 저장된 게임을 로드하도록 구분한다.
            int seqLoad = tbLoadNo.Text.Equals("") ? 0 : Int32.Parse(tbLoadNo.Text);

            int seqLastRecord = new BowlingBiz_Tx().CheckLastRecordExist(UserInfo.userID, seqLoad);

            //로드할 기록 번호를 입력 하지 않았을때는 가장 최근 기록을 출력
            if (seqLoad == 0)
            {
                if (seqLastRecord != -1)
                {
                    new BowlingBiz_Tx().SetLastRecord(seqLastRecord, GameInfo, UserInfo, GamePlay);

                    SetRepeaterBowlingScore();

                    for (int i = 1; i <= 10; i++)
                    {
                        SetBowlingPinScore(GameInfo, i, 1, GameInfo.throws[2 * (i - 1)]);
                        SetBowlingPinScore(GameInfo, i, 2, GameInfo.throws[2 * (i - 1) + 1]);
                        SetBowlingFrameScore(i, GameInfo.score[i - 1]);
                    }
                    SetBowlingPinScore(GameInfo, 10, GamePlay.BONUS_TRUE, GameInfo.throws[20]);

                    GameInfo.recordSeq = seqLastRecord;
                }
                else
                {
                    Response.Write("<script>alert('저장된 게임이 없습니다')</script>");
                }
            }
            //로드할 기록 번호 입력시
            else
            {
                if (seqLastRecord != -1)
                {
                    new BowlingBiz_Tx().SetLastRecord(seqLoad, GameInfo, UserInfo, GamePlay);

                    SetRepeaterBowlingScore();

                    for (int i = 1; i <= 10; i++)
                    {
                        SetBowlingPinScore(GameInfo, i, 1, GameInfo.throws[2 * (i - 1)]);
                        SetBowlingPinScore(GameInfo, i, 2, GameInfo.throws[2 * (i - 1) + 1]);
                        SetBowlingFrameScore(i, GameInfo.score[i - 1]);
                    }
                    SetBowlingPinScore(GameInfo, 10, GamePlay.BONUS_TRUE, GameInfo.throws[20]);

                    GameInfo.recordSeq = seqLoad;
                }
                else
                {
                    Response.Write("<script>alert('저장된 게임이 없습니다')</script>");
                }

            }

            tbLoadNo.Text = "";

        }



        /// <summary>
        /// 기록 보기 버튼의 이벤트입니다.
        /// 유저 아이디를 전달하며 호출합니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnRecordPage_Click(object sender, EventArgs e)
        {
            Response.Redirect("BowlingScoreRecord.aspx?userID=" + UserInfo.userID);
        }

        /// <summary>
        /// 웹 페이지의 입력된 핀값들의 레이블에 값을 셋합니다.
        /// 셋하면서 점수에 따라 표시형식을 지정합니다.(ex: 스트라이크 'X'...)
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="gameInfo">현재 게임의 진행 정보</param>
        /// <param name="frameNo">현재 진행 프레임 번호</param>
        /// <param name="throwCnt">현재 프레임의 던진 횟수</param>
        /// <param name="score">현재 입력된 롤 개수</param>
        public void SetBowlingPinScore(GameInfo gameInfo, int frameNo, int throwCnt, int score)
        {   
            String sLabelName = "LblFrame" + frameNo.ToString() + throwCnt.ToString();
            gameInfo.SetPinScore(frameNo, throwCnt, score);
            Label LblFrame = (Label) FindControl(sLabelName);

            if (frameNo >= 1 && frameNo < 10)
            {
                if (gameInfo.frameState[frameNo - 1] == 2 && throwCnt == 1)
                {
                    LblFrame.Text = "X";
                }
                else if (gameInfo.frameState[frameNo - 1] == 1 && throwCnt == 2)
                {
                    LblFrame.Text = "/";
                }
                else
                {
                    LblFrame.Text = "" + score;
                }
            }
            else if (frameNo == 10)
            {
                if (gameInfo.frameState[frameNo - 1] == 2)
                {
                    LblFrame.Text = "X";
                }

                else if (gameInfo.frameState[frameNo - 1] == 1)
                {
                    LblFrame.Text = "/";
                }
                else
                {
                    LblFrame.Text = "" + score;
                }
            }
        }



        /// <summary>
        /// 웹 페이지의 각 프레임의 스코어를 셋합니다.
        /// WaitFrameScore 클래스를 사용하여 스트라이크와 스페어의 점수표시 딜레이를 확인합니다.
        /// </summary>
        /// <remarks>
        /// 작성자: 권혁준
        /// </remarks>
        /// <param name="gameInfo">현재 게임 진행 정보</param>
        /// <param name="frameNo">현재 프레임 번호</param>
        /// <param name="score">현재 프레임의 던진 값</param>
        public void SetBowlingFrameScore(GameInfo gameInfo, int frameNo, int score)
        {
            //waitFrameList에서 waitNo값이 0이면 딜레이가 0이란 의미로 값을 출력
            for(int i=0; i<gameInfo.waitFrameList.Count && i<10; i++)
            {
                WaitFrameScore wfs = (WaitFrameScore) gameInfo.waitFrameList[i];
                
                gameInfo.SetFrameScore(wfs.frameNo, wfs.waitScore);

                if (wfs.waitNo == 0)
                {
                    String strLabelName = "LblFrame" + wfs.frameNo.ToString() + "Tot";

                    Label LblFrame = (Label)FindControl(strLabelName);

                    int idxFrame = wfs.frameNo - 1;
                    if (idxFrame > 0)
                    {
                        //실제 스코어에 기록되는 누적값
                        gameInfo.score[idxFrame] += gameInfo.score[idxFrame - 1];
                    }
                    
                    LblFrame.Text = "" + gameInfo.score[idxFrame];
                }
                

            }
        }

        public void SetBowlingFrameScore(int frameNo, int score)
        {
            
            String strLabelName = "LblFrame" + frameNo.ToString() + "Tot";

            Label LblFrame = (Label)FindControl(strLabelName);

            LblFrame.Text = "" + score;
                
        }


        public void btnBack_Click(object sender, EventArgs e)
        {
            Response.Redirect("BowlingLogin.aspx");
        }

        /// <summary>
        /// 스코어 테이블을 클리어
        /// </summary>
        public void ClearFrame()
        {
            LblFrame11.Text = "";
            LblFrame12.Text = "";
            LblFrame21.Text = "";
            LblFrame22.Text = "";
            LblFrame31.Text = "";
            LblFrame32.Text = "";
            LblFrame41.Text = "";
            LblFrame42.Text = "";
            LblFrame51.Text = "";
            LblFrame52.Text = "";
            LblFrame61.Text = "";
            LblFrame62.Text = "";
            LblFrame71.Text = "";
            LblFrame72.Text = "";
            LblFrame81.Text = "";
            LblFrame82.Text = "";
            LblFrame91.Text = "";
            LblFrame92.Text = "";
            LblFrame101.Text = "";
            LblFrame102.Text = "";
            LblFrame103.Text = "";
            LblFrame1Tot.Text = "";
            LblFrame2Tot.Text = "";
            LblFrame3Tot.Text = "";
            LblFrame4Tot.Text = "";
            LblFrame5Tot.Text = "";
            LblFrame6Tot.Text = "";
            LblFrame7Tot.Text = "";
            LblFrame8Tot.Text = "";
            LblFrame9Tot.Text = "";
            LblFrame10Tot.Text = "";
        }
        
        /// <summary>
        /// 임시 함수 새로 만든 테이블을 truncate 한다
        /// 테이블의 구조가 완벽하지 않아서 조건 검색이 어려움. 그래서 10개의 프레임 Row까지 입력
        /// 데이터를 insert하기 전에 truncate한다.
        /// 테이블 이전이 완료되면 기존 테이블은 DROP 한다.
        /// </summary>
        public void SetTruncateBowlingFrameScore()
        {
            using (BowlingBiz_Tx bowlingBiz_Tx = new BowlingBiz_Tx())
            {
                bowlingBiz_Tx.DeleteBowlingFrameScore();
            }
        }
        
        /// <summary>
        /// 리피터에 데이터 바인딩
        /// </summary>
        public void SetRepeaterBowlingScore()
        {
            BowlingHyukwon_SetScoreT[] bhssArr = new BowlingBiz_Tx().GetBowlingScore_1_9();
            BowlingHyukwon_SetScoreT bhss = new BowlingBiz_Tx().GetBowlingScore_10();
            repBowlingScore.DataSource = bhssArr;
            repBowlingScore.DataBind();

            if (bhss == null)
                return;

            LblThrow_10_1.Text = "" + bhss.__THROW1;
            LblThrow_10_2.Text = "" + bhss.__THROW2;
            LblThrow_10_3.Text = "" + bhss.__THROW3;
            LblScore_10.Text = "" + bhss.__SCORE;
        }
    
    }
}